package logx

import (
	"fmt"
	"github.com/gookit/color"
	"strings"
	"time"
)

const (
	panicLevel = iota
	fatalLevel
	errorLevel
	warnLevel
	infoLevel
	debugLevel
	traceLevel
)

var logMap = map[int]func(a ...any) string{
	traceLevel: color.New(color.FgGray, color.OpBold).Renderln,
	infoLevel:  color.New(color.FgGray, color.BgBlack, color.OpBlink).Renderln,
	debugLevel: color.New(color.FgLightBlue, color.BgBlack, color.OpBlink).Renderln,
	warnLevel:  color.New(color.FgYellow, color.BgBlack, color.OpBlink).Renderln,
	errorLevel: color.New(color.FgMagenta, color.BgBlack, color.OpBold).Renderln,
	fatalLevel: color.New(color.FgLightRed, color.BgDefault, color.OpBlink).Renderln,
	panicLevel: color.New(color.FgCyan, color.BgDarkGray, color.OpBlink).Renderln,
}
var logString = map[int]string{
	traceLevel: "Trace",
	infoLevel:  "Info",
	debugLevel: "Debug",
	warnLevel:  "Warn",
	errorLevel: "Error",
	fatalLevel: "Fatal",
	panicLevel: "Panic",
}

type logColor struct {
	logFormat logFormat
}
type logFormat struct {
}

func (r logFormat) pre(level string, txt string) string {
	var builder strings.Builder
	now := time.Now().Format(time.DateTime)
	builder.WriteString("[")
	builder.WriteString(now)
	builder.WriteString("] ")
	builder.WriteString("[")
	builder.WriteString(level)
	builder.WriteString("] ")
	builder.WriteString(txt)
	return builder.String()
}

func (l logColor) log(level int, a ...any) {
	if v, ok := logMap[level]; ok {
		if v2, ok2 := logString[level]; ok2 {
			fmt.Print(v(l.logFormat.pre(v2, fmt.Sprintln(a...))))
		}
	} else {
		fmt.Print(v(l.logFormat.pre("Info", fmt.Sprintln(a...))))
	}
}
func (l logColor) logf(level int, format string, a ...any) {
	if v, ok := logMap[level]; ok {
		if v2, ok2 := logString[level]; ok2 {
			fmt.Print(v(l.logFormat.pre(v2, fmt.Sprintf(format, a...))))
		}
	} else {
		fmt.Print(v(l.logFormat.pre("Info", fmt.Sprintf(format, a...))))
	}
}

var logger = logColor{}

func Panic(a ...any) {
	logger.log(panicLevel, a...)
}
func Info(a ...any) {
	logger.log(infoLevel, a...)
}
func Fatal(a ...any) {
	logger.log(fatalLevel, a...)
}
func Error(a ...any) {
	logger.log(errorLevel, a...)
}
func Warn(a ...any) {
	logger.log(warnLevel, a...)
}
func Debug(a ...any) {
	logger.log(debugLevel, a...)
}
func Trace(a ...any) {
	logger.log(traceLevel, a...)
}

func PanicLf(format string, a ...any) {
	logger.logf(panicLevel, format, a...)
}
func InfoLf(format string, a ...any) {
	logger.logf(infoLevel, format, a...)
}
func FatalLf(format string, a ...any) {
	logger.logf(fatalLevel, format, a...)
}
func ErrorLf(format string, a ...any) {
	logger.logf(errorLevel, format, a...)
}
func Warnf(format string, a ...any) {
	logger.logf(warnLevel, format, a...)
}
func Debugf(format string, a ...any) {
	logger.logf(debugLevel, format, a...)
}
func TraceLf(format string, a ...any) {
	logger.logf(traceLevel, format, a...)
}
